package cn.ecnu.paper.service.impl;

import cn.ecnu.paper.mapper.PaperMapper;
import cn.ecnu.paper.service.PublisherService;
import cn.ecnu.paper.vo.PaperVo;

import cn.ecnu.vo.message.AuthorMessage;
import cn.ecnu.vo.message.FieldMessage;
import cn.ecnu.vo.message.PaperMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;


@Slf4j
@Service
public class PublisherServiceImpl implements PublisherService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Resource
    private PaperMapper paperMapper;

    @Autowired
    private ExecutorService executor;

    @Autowired
    private RestTemplate restTemplate;


    @Override
    public void insertPaperModel(PaperVo vo) {
        PaperMessage message = new PaperMessage();

        // 消息生成任务
        CompletableFuture<Void> messageTask = CompletableFuture.runAsync(() -> {
            message.setPaperId(vo.getPaperId());
            message.setTitle(vo.getTitle());
            message.setJournal(vo.getJournal());
            message.setPublishTime(LocalDateTime.ofInstant(vo.getPublishTime().toInstant(), ZoneId.of("Asia/Shanghai")));
            message.setLink(vo.getLink());
            message.setType(type2String(vo.getType()));
            message.setPosterId(vo.getPosterId());
            message.setPosterName(vo.getPosterName());
            message.setPostTime(LocalDateTime.ofInstant(vo.getPostTime().toInstant(), ZoneId.of("Asia/Shanghai")));

            if (vo.getAuthors() != null) {
                List<AuthorMessage> authors = vo.getAuthors().stream().map((author) -> {
                    AuthorMessage am = new AuthorMessage();
                    am.setAuthorId(author.getAuthorId());
                    am.setAuthorName(author.getAuthorName());
                    am.setSort(author.getSort());
                    return am;
                }).collect(Collectors.toList());
                message.setAuthors(authors);
            }


            if (vo.getBelongs() != null) {
                List<FieldMessage> fields = vo.getBelongs().stream().map(belongVo -> {
                    FieldMessage fm = new FieldMessage();
                    fm.setFieldId(belongVo.getFieldId());
                    fm.setFieldName(belongVo.getFieldName());
                    return fm;
                }).collect(Collectors.toList());
                message.setFields(fields);
            }
            message.setNoteNum(paperMapper.getNoteNumByPaperId(vo.getPaperId()));
            log.info(message.getPaperId() + "构造基本消息完成");
        }, executor);

        // abstracts获取任务
        CompletableFuture<String> abstractsTask = CompletableFuture.supplyAsync(() -> {
            ResponseEntity<String> entity = restTemplate.getForEntity(vo.getAbstracts(), String.class);
            log.info("摘要构造完成");
            return entity.getBody();
        }, executor);

        // 消息发送任务
        abstractsTask.thenAcceptBothAsync(messageTask, (body, x) -> {
            message.setAbstracts(body);
            rabbitTemplate.convertAndSend("paper.direct", "add.paper", message);
            log.info("消息发送成功");
        }, executor);
    }

    String type2String(Integer type) {
        if (type == 0) return "理论证明型";
        else if (type == 1) return "综述型";
        else if (type == 2) return "实验型";
        else if (type == 3) return "工具型";
        return "数据集论文";
    }
}
